/////precompiled////////
#include "precompiled.h"
////////////////////////


#include "frm_control_TSplitter.h"

using namespace frm;
using namespace control;

// TSplitter //////////////////////////////////////////////////////////////////

//
void TSplitter::TStyle::SetFromParent(frm::TStyle *Parent_)
{
  if (!Parent_) {
    return;
  }

  TStyle *Parent = dynamic_cast<TStyle*>(Parent_);
  
  Normal.Filler.SetFromParent(Parent->Normal.Filler);
  Normal.Cursor.SetFromParent(Parent->Normal.Cursor);
  Normal.Border.SetFromParent(Parent->Normal.Border);

  Down.Filler.SetFromParent(Parent->Down.Filler);
  Down.Cursor.SetFromParent(Parent->Down.Cursor);
  Down.Border.SetFromParent(Parent->Down.Border);
}

//
svl::TInfoParam TSplitter::TStyle::AddInfoTo(svl::TInfoParam Info)
{
  return frm::TStyle::AddInfoTo(Info)
   .Add("Weight" ,Weight)
   .Add("Normal" ,Normal)
   .Add("Down"   ,Down)
  ;
}

// vert ///////////////////////////////////////////////////////////////////////

//
void TSplitter::TStyleVert::SetDefault()
{
  Normal.Cursor.Set(cursor::TCursorWin(IDC_SIZEWE));
  Normal.Filler.Set(filler::TColor(grf::TColor(192,192,192)));
  Down  .Cursor.Set(cursor::TCursorWin(IDC_SIZEWE));
  Down  .Filler.Set(filler::TColor(grf::TColor(192,0,0)));
  Weight = 5;
}

// horz ///////////////////////////////////////////////////////////////////////

//
void TSplitter::TStyleHorz::SetDefault()
{
  Normal.Cursor.Set(cursor::TCursorWin(IDC_SIZENS));
  Normal.Filler.Set(filler::TColor(grf::TColor(192,192,192)));
  Down  .Cursor.Set(cursor::TCursorWin(IDC_SIZENS));
  Down  .Filler.Set(filler::TColor(grf::TColor(192,0,0)));
  Weight = 3;
}

// both ///////////////////////////////////////////////////////////////////////

//
void TSplitter::TStyleBoth::SetDefault()
{
  Normal.Cursor.Set(cursor::TCursorWin(IDC_SIZENWSE));
  Normal.Filler.Set(filler::TColor(grf::TColor(0,200,0)));
  Down  .Cursor.Set(cursor::TCursorWin(IDC_SIZENWSE));
  Down  .Filler.Set(filler::TRoundRect(grf::TColor(255,255,255),grf::TColor(255,255,0)));
  Weight = 10;
}

//
TSplitter::TSplitter(TWindow &Window,ESplit Split,TPanel *CResizePrev)
:TPanel(Window)
{
  eSplit = Split;
  SetStyle(DefaultStyles().Get(Split));
  Init(Split,CResizePrev);
}

//
TSplitter::~TSplitter()
{
  delete param;
}

//
TSplitter &TSplitter::SetStyle(TStyle &V) 
{ 
  if (eSplit != V.GetESplit()) { 
    Except("SetStyle[eSplit != V.GetESplit()]");
  } 
  
  style = &V; 
  SetSize(V.Weight); 
  TPanel::SetStyle(V.Normal);    
  
  return *this;
}

//
void TSplitter::SetSize(int V)
{
  if (split.Contains(Vert)) { SetWidth(V);}
  if (split.Contains(Horz)) { SetHeight(V);}
}

//
void TSplitter::Init(ESplit Split,TPanel *CResizePrev)
{
  switch (Split)
  {
    case Vert: split << Vert;         break;
    case Horz: split << Horz;         break;
    case Both: split << Vert << Horz; break;
  }
  bool V = split.Contains(Vert);
  bool H = split.Contains(Horz);

  cResizePrev = CResizePrev; 
  cResizeNext = NULL; 
  
  param = NULL; 
  SetMinSize();

  if (V)
  {
    //Rect.X.Set(0                    ,EDirectChildren_Seq,EAlignChildren_Begin);
    //Rect.Y.Set(ECalcSize_SiblingsMax,EDirectChildren_All,EAlignChildren_Begin);
    Width_Fixed(0).Height_SiblingsMax()
     .DirectChildren_Horz()
     .WAlignChildren_Begin().HAlignChildren_Begin();
  }
  if (H)
  {
    //Rect.X.Set(ECalcSize_SiblingsMax,EDirectChildren_All,EAlignChildren_Begin);
    //Rect.Y.Set(0                    ,EDirectChildren_Seq,EAlignChildren_Begin);
    Width_SiblingsMax().Height_Fixed(0)
     .DirectChildren_Vert()
     .WAlignChildren_Begin().HAlignChildren_Begin();
  }
  SetSize(style->Weight);
}

//
void TSplitter::TComponent_Mouse(TMouse Mouse)
{
  bool V = split.Contains(Vert);
  bool H = split.Contains(Horz);

  TPanel::TComponent_Mouse(Mouse); switch (Mouse.State)
  {
    case grf::TMouse::EState_LButtonDown:
    case grf::TMouse::EState_LButtonDblClick:
    {
      GetMouse().SetCapture(this);
      delete param; param = new TParam;
      param->PtBegin = Mouse.PtClient;

      if (cResizePrev) {
        param->SizeBeginPrev = cResizePrev->GetSize();
      }
      if (cResizeNext) {
        param->SizeBeginNext = cResizeNext->GetSize();
      }

      TPanel::UpdateStyle(style->Down);
    }
    break;

    case grf::TMouse::EState_LButtonUp:
    {
      GetMouse().SetCapture(NULL);
      delete param; param = NULL;

      TPanel::UpdateStyle(style->Normal);
    }
    break;

    case grf::TMouse::EState_Move:
    {
      if (Mouse.Shift.Contains(grf::TShift::Left) && param)
      {
        grf::TPoint Delta = Mouse.PtClient - param->PtBegin;
        bool EnNextX = true,EnNextY = true;

        BeginPaint();

        if (cResizePrev)
        {
          grf::TSize NewSize = cResizePrev->GetSize();

          if (V) { NewSize.Width  = param->SizeBeginPrev.Width  + Delta.X;}
          if (H) { NewSize.Height = param->SizeBeginPrev.Height + Delta.Y;}

          NewSize.Width  = max(NewSize.Width ,minSize);
          NewSize.Height = max(NewSize.Height,minSize);

          if (V) 
          { 
            cResizePrev->GetWOrdinate().UpdateSize(NewSize.Width);
            EnNextX = (cResizePrev->GetWidth() == NewSize.Width);
          }
          if (H) 
          { 
            cResizePrev->GetHOrdinate().UpdateSize(NewSize.Height);
            EnNextY = (cResizePrev->GetHeight() == NewSize.Height);
          }
        }
        
        if (cResizeNext)
        {
          grf::TSize NewSize = cResizeNext->GetSize();

          if (V) { NewSize.Width  = param->SizeBeginNext.Width  - Delta.X;}
          if (H) { NewSize.Height = param->SizeBeginNext.Height - Delta.Y;}

          NewSize.Width  = max(NewSize.Width ,minSize);
          NewSize.Height = max(NewSize.Height,minSize);

          if (V && EnNextX) { cResizeNext->GetWOrdinate().UpdateSize(NewSize.Width);}
          if (H && EnNextY) { cResizeNext->GetHOrdinate().UpdateSize(NewSize.Height);}
        }
        
        EndPaint();
      }
    }
    break;
  }
}

//
void TSplitter::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
  TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
    SetStyle(*Style);
  }
}

// TSplitterVert //////////////////////////////////////////////////////////////

//
void TSplitterVert::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
  TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
    SetStyle(*Style);
  }
}

// TSplitterHorz //////////////////////////////////////////////////////////////

//
void TSplitterHorz::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
  TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
    SetStyle(*Style);
  }
}

// TSplitterBoth //////////////////////////////////////////////////////////////

//
void TSplitterBoth::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
  TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
    SetStyle(*Style);
  }
}
